<?php
namespace App\Services;

use App\Models\Balance;
use App\Models\ExpressType;
use App\Models\MallOrder;
use App\Models\MallOrderProduct;
use App\Models\MallOrderProductSnapshot;
use App\Models\MallProductStock;
use App\Models\MallRefund;
use App\Models\Product;

class MallOrderService {


    public static function handle($input, $action, $is_transaction = true) {
        try {
            $is_transaction && \DB::beginTransaction();
            $order = MallOrder::lockForUpdate()->find($input['order_id']);
            if (!$order)
                throw new \Exception('订单号不存在', 200);

            $ret = null;
            if ($action == 'cancel') {
                if ($order->status !=  MallOrder::STATUS_WAIT_PAY)
                    throw new \Exception('当前订单状态不允许取消', 200);

                $order->status = MallOrder::STATUS_CLOSE;
                $order->close_type = $input['close_type'];
                $order->save();

                //下面所有子单也取消
                $list = MallOrderProduct::where('order_id', $order->id)->get();
                foreach ($list as $item) {
                    $item->status = MallOrderProduct::STATUS_CANCEL;
                    $item->save();

                    if ($item->specs_str) {
                        //加规格库存
                        MallProductStock::where('product_id', $item->product_id)->where('key', $item->specs_str)->increment('stock', $item->buy_num);
                        MallProductStock::flushQueryCache();
                    }
                    $product_model = Product::find($item->product_id);
                    if ($product_model) {
                        $product_model->stock = $product_model->stock + $item->buy_num;
                        $product_model->save();
                    }
                }

            } else if($action == 'deliver') {
                if ($order->status !=  MallOrder::STATUS_WAIT_PRODUCT)
                    throw new \Exception('当前订单状态不允许操作发货', 200);

                foreach ($input['order_product_id'] as $id) {
                    $model = MallOrderProduct::find($id);
                    if ($model->status !=  MallOrderProduct::STATUS_WAIT_PRODUCT)
                        throw new \Exception('当前订单状态不允许操作发货', 200);
                    $model->status = MallOrderProduct::STATUS_DELIVER_PRODUCT;
                    $model->express_order_sn = $input['express_order_sn'];
                    $express = ExpressType::find($input['express_id']);
                    $model->express_title = $express->name;
                    $model->express_id = $express->id;
                    $model->express_start_at = date('Y-m-d H:i:s');
                    $model->save();
                }
                //零元商品不需要发货
                $exists = MallOrderProduct::where('order_id', $order->id)->where('is_zero', 0)->whereIn('status', [MallOrderProduct::STATUS_WAIT_PRODUCT])->exists();
                if (!$exists) {
                    $order->status = MallOrder::STATUS_DELIVER_PRODUCT;
                    $order->express_start_at = date('Y-m-d H:i:s');
                    $order->express_end_at = date('Y-m-d H:i:s', strtotime("+10 day"));
//                    $order->express_end_at = date('Y-m-d H:i:s', time()+10*60);
                    $order->save();
                }

            } else if($action == 'receive') {
                if ($order->status !=  MallOrder::STATUS_DELIVER_PRODUCT)
                    throw new \Exception('当前订单状态不允许操作收货', 200);

                //是否存在其他正在退货中
                $exist_other_refunding = MallOrderProduct::where('order_id', $input['order_id'])
                    ->whereIn('refund_status', [1, 2, 3])->exists();
                if ($exist_other_refunding)
                    throw new \Exception('存在退款未处理', 200);

                //修改子订单
                $list = MallOrderProduct::where('order_id', $order->id)
                    ->withCertain('product', ['rate'])->withCertain('user', ['rec_merchant_id', 'benefit_user'])->where('status', MallOrderProduct::STATUS_DELIVER_PRODUCT)->get();
                if ($list) {
                    foreach ($list as $item) {
                        $item->status = MallOrderProduct::STATUS_FINISH;
                        $item->save();

                        //商品销量 + 1
                        $product = Product::find($item->product_id);
                        if ($product) {
                            if ($item->is_zero) {
                                $product->zero_sale_num = $product->zero_sale_num + 1;
                                continue;
                            }
                            else
                                $product->sale_num = $product->sale_num + $item->buy_num;
                            $product->save();
                        }
                        $title = MallOrderProductSnapshot::find($item->product_snapshot_id)->title;
                        //佣金
                        if ($item->product->rate && $item->user->rec_merchant_id) {
                            $amount = $item->product->rate * $item->paid_amount / 100;
                            if ($amount)
                                BalanceService::store($item->user->benefit_user, $item->user_id, $item->user->rec_merchant_id, $item->paid_amount, Balance::TYPE_MALL,
                                    $item->id, $item->order_sn, $title, false, 0, $amount);
                        }
                    }
                }
                $order->status = MallOrder::STATUS_FINISH;
                $order->save();

            } else if($action == 'refund') {
                if (!in_array($order->status ,  [MallOrder::STATUS_WAIT_PRODUCT , MallOrder::STATUS_DELIVER_PRODUCT]))
                    throw new \Exception('当前订单状态不允许申请退款', 200);

                $model = MallOrderProduct::withCertain('product', ['title'])->find($input['order_product_id']);

                if (!in_array($model->status , [MallOrderProduct::STATUS_WAIT_PRODUCT, MallOrderProduct::STATUS_DELIVER_PRODUCT]))
                    throw new \Exception('当前订单状态不允许申请退款!', 200);

                $paid_amount = $input['total_amount'] ?? null;


                $actual_amount = $model->paid_amount + ($model->assign_fare * 100);

                if ($paid_amount) {
                    if ($paid_amount <= 0)
                        throw new \Exception('金额必须大于0', 200);
                    if (  ($paid_amount * 100)  > $actual_amount )
                        throw new \Exception('填写金额不能大于实际金额', 200);
                    $paid_amount  = $paid_amount * 100;
                } else {
                    $paid_amount = $actual_amount;
                }

                $input['is_return_product'] = $input['is_return_product'] ?? 0;
                if ($model->status == MallOrderProduct::STATUS_WAIT_PRODUCT) {
                    if( $input['is_return_product']  == 1 ) {
                       throw new \Exception('请申请仅退款操作', 200);
                    }
                }

                //判断是否已经申请过
                $is_apply = MallRefund::where('order_product_id', $input['order_product_id'])->where('user_id', $input['user_id'])->exists();
                if ($is_apply)
                    throw new \Exception('只允许申请退款一次', 200);

                $refund = MallRefund::create([
                    'user_id' => $input['user_id'],
                    'product_snapshot_id' => $model->product_snapshot_id,
                    'is_return_product' => $input['is_return_product'],
                    'order_product_id' => $input['order_product_id'],
                    'refund_sn' => create_order_no('r'),
                    'status' => MallRefund::STATUS_WAIT_REFUND,
                    'apply_start_at' => date('Y-m-d H:i:s'),
                    'reason' => $input['reason'] ?? '',
                    'product_status' => $input['product_status'] ?? '',
                    'actual_amount' => $actual_amount,
                    'paid_amount' => $paid_amount,
                    'pay_type' => $order->pay_type,
                    'fare' => $model->assign_fare * 100,
                    'desc' => $input['desc'] ?? null,
                    'file' => $input['file'] ?? null,
                ]);
                $model->refund_status = MallRefund::STATUS_WAIT_REFUND;
                $model->save();

                //停止自动收货时间
                if ($order->status == MallOrder::STATUS_DELIVER_PRODUCT) {
                    $order->express_end_at = date('Y-m-d H:i:s', strtotime("+30 day"));
                    $order->save();
                }
                $ret = $refund;
            }
            $is_transaction && \DB::commit();
            return $ret;
        } catch (\Exception $e) {
            if ($e->getCode() != 200)
                \Log::error($e);
            $is_transaction && \DB::rollBack();
            throw new \Exception($e->getMessage());
        }

    }

    static function getSaleNum($product_id, $arr_key = null) {
        return MallOrderProduct::where('product_id', $product_id)->when($arr_key, function ($q) use($arr_key) {
            $q->whereIn('specs_str', $arr_key);
        })->where('sale_num', 1)->groupBy('specs_str')->selectRaw('count(specs_str) as total, specs_str')->pluck('total', 'specs_str')->all();
    }

    static function specsKey($arr) {
        if (!is_array($arr))
            $arr = json_decode($arr, true);
        unset($arr['amount'], $arr['vip_amount'], $arr['stock'],$arr['weight'], $arr['key'], $arr['vip_price'], $arr['price']);
        ksort($arr);
        $str = '';
        foreach ($arr as $key => $val) {
            $str .= $key . $val;
        }
        return $str;
    }


}
